#include "menu_handle.h"

#include "fui.h"

#include "drv_lcd.h"
#include "drv_adc.h"
#include "drv_tmr.h"
#include "drv_key.h"
#include "drv_vbus_sw.h"

#include "lcd.h"

#include <string.h>

menu_idx_t CURR_MENU = MENU_IDX_HOME;
hub_state_t hub_state;

char print_buf[64];

static void menu_reload_vbus_status_cb(uint8_t idx);
static void menu_about_cb(uint8_t idx);
static void menu_exit_menu1_cb(uint8_t idx);
static void menu_vbus1_cb(uint8_t idx);
static void menu_vbus2_cb(uint8_t idx);
static void menu_vbus3_cb(uint8_t idx);
static void menu_vbus4_cb(uint8_t idx);

fui_menu_item_t first_menu[] = {
    {
        .title = "@@@ EXIT @@@",
        .callback = menu_exit_menu1_cb,
    },
    {
        .title = "VBUS1 OFF",
        .callback = menu_vbus1_cb,
    },
    {
        .title = "VBUS1 OFF",
        .callback = menu_vbus2_cb,
    },
    {
        .title = "VBUS2 OFF",
        .callback = menu_vbus3_cb,
    },
    {
        .title = "VBUS2 OFF",
        .callback = menu_vbus4_cb,
    },
    {
        .title = "Reload VBUS Status",
        .callback = menu_reload_vbus_status_cb,
    },
    {
        .title = "About",
        .callback = menu_about_cb,
    }
};

static inline uint16_t get_usb_curr_fg(uint8_t idx)
{
    if(hub_state.port_state[idx].ovc_state)
    {
        return WHITE;
    }
    
    switch(idx)
    {
        case 0:
            if(!VBUS1_STATRD())
            {
                return WHITE;
            }
            break;
        case 1:
            if(!VBUS2_STATRD())
            {
                return WHITE;
            }
            break;
        case 2:
            if(!VBUS3_STATRD())
            {
                return WHITE;
            }
            break;
        case 3:
            if(!VBUS4_STATRD())
            {
                return WHITE;
            }
            break;
        default:
            break;
    }
    
    return 0x7FFC;
}

static inline uint16_t get_usb_curr_bg(uint8_t idx)
{
    if(hub_state.port_state[idx].ovc_state)
    {
        return RED;
    }
    
    switch(idx)
    {
        case 0:
            if(!VBUS1_STATRD())
            {
                return RED;
            }
            break;
        case 1:
            if(!VBUS2_STATRD())
            {
                return RED;
            }
            break;
        case 2:
            if(!VBUS3_STATRD())
            {
                return RED;
            }
            break;
        case 3:
            if(!VBUS4_STATRD())
            {
                return RED;
            }
            break;
        default:
            break;
    }
    
    return BLACK;
}

void task_display_handle(void)
{
    if(task_disp_tick < 100)
    {
        return;
    }
    task_disp_tick = 0;
    if(CURR_MENU != MENU_IDX_HOME)
    {
        return;
    }

    // ========================================================
    for(uint8_t i =0; i < 4;i++)
    {
        snprintf(print_buf, sizeof(print_buf), "%sUSB%d = %.2fmA, %.2fW    ",
            hub_state.port_state[i].ovc_state ? "$OCP$" : "", i + 1,hub_state.port_state[i].current, hub_state.port_state[i].power);
        LCD_ShowString(0, 18 * i, (uint8_t*)print_buf, get_usb_curr_fg(i), get_usb_curr_bg(i), 20,0);
    }
    // ========================================================
    snprintf(print_buf, sizeof(print_buf), "VBUS# = %.2fV%s           ", hub_state.vbus_value, hub_state.ovp_flag ? " $OVP$" : "");
    LCD_ShowString(0, 72, (uint8_t*)print_buf, hub_state.ovp_flag ? WHITE : 0xFF50, hub_state.ovp_flag ? RED : BLACK, 20,0);
    
    snprintf(print_buf, sizeof(print_buf), "VIN# = %.2fV, %.2fC       ", hub_state.vin_value, hub_state.chip_temp);
    LCD_ShowString(0, 90, (uint8_t*)print_buf, 0xFF50, BLACK, 20,0);

    snprintf(print_buf, sizeof(print_buf), "ALL = %.2fmA, %.2fW       ", hub_state.all_current, hub_state.all_power);
    LCD_ShowString(0, 108, (uint8_t*)print_buf, 0x8F30, BLACK, 20,0);

    snprintf(print_buf, sizeof(print_buf), "Energy = %.4fWh          ", hub_state.all_energy);
    LCD_ShowString(0, 126, (uint8_t*)print_buf, 0x8F30, BLACK, 20,0);

    // LCD_ShowString(0, 108, (uint8_t*)"LCDUSBHUB 20240616 V1.2", WHITE, BLACK, 20,0);
}

void display_about_sw(void)
{
    LCD_ShowString(0, 222, (uint8_t*)"LCDUSBHUB 20241208 V1.7", WHITE, BLACK, 20,0);
}

static void menu_about_cb(uint8_t idx)
{
    fui_showmsgbox("About", "LCDUSBHUB @FanHuaCloud", NULL);
    display_about_sw();
}

static void menu_exit_menu1_cb(uint8_t idx)
{
    CURR_MENU = MENU_IDX_HOME;
    
    LCD_Fill(0, 0, LCD_W, LCD_H, BLACK);
    task_display_handle();
    display_about_sw();
}

void vbus_status_load(void)
{
    // load VBUS sw status
    if(VBUS1_STATRD())
    {
        strcpy(first_menu[1].title, "VBUS1 OFF");
    }
    else
    {
        strcpy(first_menu[1].title, "VBUS1 ON");
    }
    if(VBUS2_STATRD())
    {
        strcpy(first_menu[2].title, "VBUS2 OFF");
    }
    else
    {
        strcpy(first_menu[2].title, "VBUS2 ON");
    }
    if(VBUS3_STATRD())
    {
        strcpy(first_menu[3].title, "VBUS3 OFF");
    }
    else
    {
        strcpy(first_menu[3].title, "VBUS3 ON");
    }
    if(VBUS4_STATRD())
    {
        strcpy(first_menu[4].title, "VBUS4 OFF");
    }
    else
    {
        strcpy(first_menu[4].title, "VBUS4 ON");
    }
}

static uint8_t menu_ovp_flag(void)
{
    if(hub_state.ovp_flag)
    {
        fui_showmsgbox("ERROR", "OVP Error", "Please Restart the power");
        vbus_status_load();
        return 1;
    }
    return 0;
}

static void menu_vbus1_cb(uint8_t idx)
{
    if(menu_ovp_flag())
    {
        return;
    }
    
    if(VBUS1_STATRD())
    {
        VBUS1_OFF();
        fui_showmsgbox("Msg", "VBUS1 OFF OK", NULL);
    }
    else
    {
        // Clear usb_ovcstat when on
        hub_state.port_state[0].ovc_state = 0;
        VBUS1_ON();
        fui_showmsgbox("Msg", "VBUS1 ON OK", NULL);
    }
    vbus_status_load();
}

static void menu_vbus2_cb(uint8_t idx)
{
    if(menu_ovp_flag())
    {
        return;
    }
    
    if(VBUS2_STATRD())
    {
        VBUS2_OFF();
        fui_showmsgbox("Msg", "VBUS2 OFF OK", NULL);
    }
    else
    {
        // Clear usb_ovcstat when on
        hub_state.port_state[1].ovc_state = 0;
        VBUS2_ON();
        fui_showmsgbox("Msg", "VBUS2 ON OK", NULL);
    }
    vbus_status_load();
}

static void menu_vbus3_cb(uint8_t idx)
{
    if(menu_ovp_flag())
    {
        return;
    }
    
    if(VBUS3_STATRD())
    {
        VBUS3_OFF();
        fui_showmsgbox("Msg", "VBUS3 OFF OK", NULL);
    }
    else
    {
        // Clear usb_ovcstat when on
        hub_state.port_state[2].ovc_state = 0;
        VBUS3_ON();
        fui_showmsgbox("Msg", "VBUS3 ON OK", NULL);
    }
    vbus_status_load();
}

static void menu_vbus4_cb(uint8_t idx)
{
    if(menu_ovp_flag())
    {
        return;
    }
    
    if(VBUS4_STATRD())
    {
        VBUS4_OFF();
        fui_showmsgbox("Msg", "VBUS4 OFF OK", NULL);
    }
    else
    {
        // Clear usb_ovcstat when on
        hub_state.port_state[3].ovc_state = 0;
        VBUS4_ON();
        fui_showmsgbox("Msg", "VBUS4 ON OK", NULL);
    }
    vbus_status_load();
}

static void menu_reload_vbus_status_cb(uint8_t idx)
{
    vbus_status_load();
    fui_draw_menu();
}

void menu_key_handle(void)
{
    if(CURR_MENU == MENU_IDX_HOME && key1_click_flag)
    {
        key1_click_flag = 0;
        key2_click_flag = 0;
        key3_click_flag = 0;
        
        CURR_MENU = MENU_IDX_MENU1;
        
        vbus_status_load();
        fui_load_menu(first_menu, sizeof(first_menu) / sizeof(fui_menu_item_t));
    }
    if(CURR_MENU == MENU_IDX_HOME)
    {
        return;
    }
    
    if(key1_click_flag)
    {
        key1_click_flag = 0;
        fui_keyevt_enter();
    }
    if(key2_click_flag)
    {
        key2_click_flag = 0;
        fui_keyevt_down();
    }
    if(key3_click_flag)
    {
        key3_click_flag = 0;
        fui_keyevt_up();
    }
}
